import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;


class MyBlockQueue {
   /* int head = 0;
    int tail = 0;
    int size = 0;*/
   volatile int head = 0;
    volatile int tail = 0;
    volatile int size = 0;

    public String[] elem;
    public MyBlockQueue(int capacity) {
        elem = new String[capacity];
    }
    //入队
    public void put(String s) throws InterruptedException {
        synchronized (this) {
           /* if(size == elem.length) {
                System.out.println("队列满，阻塞等待");
                this.wait();
            }*/
            while (size >=elem.length) {
                //循环等待确认，防止不是被notify唤醒
                try {
                    this.wait();
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            elem[tail] = s;//队尾入
            size++;
            if(tail >= elem.length-1) tail=0;
            else tail++;
            this.notify();
        }
    }
    //出队
    public String take() throws InterruptedException {
        synchronized (this) {
           /* if(size == 0) {
                System.out.println("队列空");
                this.wait();
            }*/
            while (size ==0) {
                try {
                    this.wait();
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            String tmp = elem[head];
            size--;
            if(head == elem.length-1) head = 0;
            else head++;
            this.notify();
            return tmp;
        }
    }
}

public class Test {
    public static void main(String[] args) throws InterruptedException {
        MyBlockQueue myBlockQueue = new MyBlockQueue(10);
        Thread t1 = new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    System.out.println("生成1：");
                    myBlockQueue.put("1");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        Thread t2 = new Thread(()->{
            for (int i = 0; i < 30; i++) {
                String tmp = null;
                try {
                    tmp = myBlockQueue.take();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("消费："+tmp);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t1.start();
        t2.start();
    }

    public static void main3(String[] args) throws InterruptedException {
        //再次复习阻塞队列的使用
        BlockingQueue<Integer> blockingQueue = new ArrayBlockingQueue<>(100);
        Thread t1 = new Thread(()->{
            for (int i = 0; i < 5000; i++) {
                try {
                    blockingQueue.put(i);
                    Thread.sleep(1000);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2 = new Thread(()->{
            for (int i = 0; i < 5000; i++) {
                try {
                    int tmp = blockingQueue.take();
                    System.out.println(tmp);
                }catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        t2.start();
    }
    public static void main1(String[] args) {
        //阻塞队列的使用
        BlockingDeque<Integer> blockingDeque = new LinkedBlockingDeque<>();

        Thread t1 = new Thread(()->{
            int count=0;
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                try {
                    blockingDeque.put(count);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("生产者："+count++);
            }
        });
        Thread t2 = new Thread(()->{
            for (int i = 0; i < 100; i++) {
                int tmp = 0;
                try {
                    tmp = blockingDeque.take();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println("消费者："+tmp);
            }
        });
        t1.start();
        t2.start();

    }
}
